package Client.SearchDB
import java.util.LinkedList
import Search.Parameter
import org.hibernate.cfg.Configuration
import org.hibernate.SessionFactory
import org.hibernate.Session

/**
 * Object to manage the tagging database
 */
object DataBaseManager {
  /**
   * Method to search the database with given parameters and return results
   * @param tags the received tags
   * @returns the search results
   */
  def search (tags:LinkedList[Parameter]):java.util.List[String]={
    
    val cfg = new Configuration()
    var sessionFactory = null.asInstanceOf[SessionFactory]
    var session = null.asInstanceOf[Session]
    try{
      //connect to the database
      sessionFactory = cfg.configure().buildSessionFactory()
      session = sessionFactory.openSession()
      var queryStr="select t1.file from"
      var num=tags.size
      var newTags=new Array[Parameter](num)
      for (i <- 0 until num-1)
        newTags.update(i, tags.remove(0));
      var yes=newTags.filter((p:Parameter) => p.no==true)
      var no=newTags.filter((p:Parameter) => p.no==false)
      var yesNum=yes.size
      var noNum=no.size
      //construct the HQL query
      for (i <- 1 until yesNum-1)
        queryStr=queryStr+" Tags as t"+i+",";
      queryStr=queryStr+" Tags as t"+yesNum+" where "
      for (i <- 1 until yesNum-1)
        queryStr=queryStr+"t"+i+".file=t"+(i+1)+".file and ";
      for (i <- 1 until yesNum-1)
        queryStr=queryStr+"t"+i+".tag='"+yes.apply(i-1).par+"' and ";
      queryStr=queryStr+"t"+yesNum+".tag='"+yes.apply(yesNum-1).par+"'"
      if (!no.isEmpty){
        queryStr=queryStr+" and not exists (from Tags as t where t.file=t1.file and (t.tag='"+no.apply(0).par+"' or"
        for (i <-2 until noNum)
          queryStr=queryStr+" t.tag='"+no.apply(i).par+"'";
        queryStr=queryStr+"))"
      }
      //send the query to the database and return results
      var query=session.createQuery(queryStr)
      var res=query.list.asInstanceOf[java.util.List[String]]
      return res
    }    
    catch {
      case (e:Exception) => return null
    }
    
  }
}